package com.blackshadowgame.rps;

import ohos.utils.Parcel;
import ohos.utils.Sequenceable;

import java.util.ArrayList;
import java.util.List;

public class GameResultData implements Sequenceable {
    public int state = GameCode.GAME_STATE_NEW;
//    public int playerCount = 0;
    public List<GameInput> playerInputs = new ArrayList<>();
    public int winner = -1;

    @Override
    public boolean marshalling(Parcel parcel) {
        parcel.writeInt(state);

        if(state>0){
            int playerCount = playerInputs.size();
            parcel.writeInt(playerCount);
            for(GameInput input: playerInputs){
                parcel.writeInt(input.playerId);
                parcel.writeInt(input.inputCode);
            }
            parcel.writeInt(winner);
        }

        return true;
    }

    @Override
    public boolean unmarshalling(Parcel parcel) {
        state = parcel.readInt();
        if(state>0){
            int playerCount = parcel.readInt();
            for(int i=0;i<playerCount;i++){
                GameInput input = new GameInput();
                input.playerId = parcel.readInt();
                input.inputCode = parcel.readInt();
                playerInputs.add(input);
            }
            winner = parcel.readInt();
        }

        return true;
    }

    public synchronized void newGame(boolean keepPlayers){
        if(!keepPlayers){
            playerInputs.clear();
            state = GameCode.GAME_STATE_NEW;
            winner = -1;
        }else{
            for(int i=0;i<playerInputs.size();i++){
                playerInputs.get(i).inputCode = InputCode.NONE_0;
            }
            state = GameCode.GAME_STATE_WAITING_FOR_INPUT;
            winner = -1;
        }
    }

    public boolean hasEnoughPlayer(){
        return playerInputs.size()>=2;
    }

    public synchronized boolean joinPlayer(int pid){
        GameInput input = null;
        if(playerInputs.size()>=2){
            return false;
        }

        boolean isNewPlayer = true;
        for(int i=0;i<playerInputs.size();i++){
            if(playerInputs.get(i).playerId == pid){
                isNewPlayer = false;
                break;
            }
        }

        if(isNewPlayer){
            GameInput player = new GameInput();
            player.playerId = pid;
            player.inputCode = InputCode.NONE_0;
            playerInputs.add(player);
        }

        if(playerInputs.size()<2){
            state = GameCode.GAME_STATE_WAITING_FOR_PLAYER;
        }else{
            state = GameCode.GAME_STATE_WAITING_FOR_INPUT;
        }

        return isNewPlayer;
    }

    public synchronized boolean removePlayer(int pid){
        boolean valid = false;
        for(int i=0;i<playerInputs.size();i++){
            if(playerInputs.get(i).playerId == pid){
                playerInputs.remove(i);
                valid = true;
                break;
            }
        }

        if(valid && playerInputs.size()>0){
            if(playerInputs.get(0).playerId == 0){
                // 只剩下AI的话，也移除AI
                playerInputs.remove(0);
            }
        }

        if(playerInputs.size()==1){
            state = GameCode.GAME_STATE_WAITING_FOR_PLAYER;
        }else if(playerInputs.size() == 0){
            state = GameCode.GAME_STATE_NEW;
        }

        return true;
    }

    public synchronized boolean addInput(int pid, int inputCode){
        boolean valid = false;
        GameInput input = null;
        for(int i=0;i<playerInputs.size();i++){
            if(playerInputs.get(i).playerId == pid){
                input = playerInputs.get(i);
                break;
            }
        }

        if(input == null){
            input = new GameInput();
            input.playerId = pid;
            input.inputCode = inputCode;
            playerInputs.add(input);
            valid = true;
        }else if(input.inputCode == InputCode.NONE_0){
            input.inputCode = inputCode;
            valid = true;
        }else{
            // 已经出过拳了，不允许更改
            valid = false;
        }

//        if(playerInputs.size()<2){
//            state = GameCode.GAME_STATE_WAITING_FOR_PLAYER;
//        }else{
//            state = GameCode.GAME_STATE_WAITING_FOR_INPUT;
//        }
        return valid;
    }

    public GameInput getPlayerInput(int pid){
        GameInput input = null;
        for(int i=0;i<playerInputs.size();i++){
            if(playerInputs.get(i).playerId == pid){
                input = playerInputs.get(i);
                break;
            }
        }

        return input;
    }

    public synchronized boolean calculateWinner(){
        if(playerInputs.size()<2){
            state = GameCode.GAME_STATE_WAITING_FOR_INPUT;
            return false;
        }

        GameInput a = playerInputs.get(0);
        GameInput b = playerInputs.get(1);

        if(a.inputCode == 0 || b.inputCode == 0){
            state = GameCode.GAME_STATE_WAITING_FOR_INPUT;
            return false;
        }

        int result = InputCode.calculateWinner(a.inputCode, b.inputCode);
        if(result == 0){
            winner = -1;
        }else if(result>0){
            winner = a.playerId;
        }else{
            winner = b.playerId;
        }

        // 胜负决出，本局结束
        state = GameCode.GAME_STATE_FINISHED;
        return true;
    }

    public int[] getPlayers(){
        int[] players = new int[playerInputs.size()];
        int i=0;
        for(GameInput input: playerInputs){
            players[i] = playerInputs.get(i).playerId;
        }
        return players;
    }

    public String getInfo(){
        String info = "";
        if(state == GameCode.GAME_STATE_NEW){
            info = "新游戏";
        }else{
            for(GameInput player: playerInputs){
                info += String.format("玩家[%d]:[%s] ", player.playerId, InputCode.getInputCodeName(player.inputCode));
            }
            if(state == GameCode.GAME_STATE_FINISHED){
                if(winner<0){
                    info += " => 打平";
                }else{
                    info += String.format(" => 胜者：[%d]", winner);
                }
            }
        }
        return info;
    }
}
